#ifndef __IMPORT_VRSCENE__H
#define __IMPORT_VRSCENE__H

#include <fstream>
#include <functional>
#include <numeric>
#include <list>
#include <vector>
#include <string>

#include <boost/spirit/include/classic.hpp>
#include <boost/algorithm/string.hpp>

namespace vrscene
{

  using namespace boost::spirit::classic;

  typedef  std::pair<std::string, std::string> Entry;
  typedef  std::list<Entry > Entries;
  typedef  std::pair<std::string, std::pair<std::string, Entries> > Section;
  typedef  std::list<Section> vrsceneData;


  struct add_section
  {
    add_section(vrsceneData & data) : data_(data) {}

    void operator()(char const* p, char const* q) const
    {
      std::string s(p,q);
      boost::algorithm::trim(s);
      std::string sect_type, sect_name;
      size_t temp;

      temp=s.find_first_of(' ');
      sect_type = s.substr(0, temp);
      sect_name = s.substr(temp+1, s.size()-temp);

      data_.push_back(Section(sect_type, std::pair< std::string, Entries>(sect_name, Entries()) ));
    }

    vrsceneData & data_;
  };

  struct add_key
  {
    add_key(vrsceneData & data) : data_(data) {}

    void operator()(char const* p, char const* q) const
    {
      std::string s(p,q);
      boost::algorithm::trim(s);
      data_.back().second.second.push_back(Entry(s, std::string()) );
    }

    vrsceneData & data_;
  };

  struct add_value
  {
    add_value(vrsceneData & data) : data_(data) {}

    void operator()(char const* p, char const* q) const
    {
      data_.back().second.second.back().second.assign(p, q);
    }

    vrsceneData & data_;
  };


  struct vrscene_parser : public grammar<vrscene_parser>
  {
    vrscene_parser(vrsceneData & data) : data_(data) {}

    template <typename T>
    struct definition
    {
      rule<T> inidata, section, entry, ident, value, stringSpaces, spaces;

      rule<T> const& start() const { return inidata; }

      definition(vrscene_parser const& self)
      {
        inidata = *section;

        section = ident[add_section(self.data_)]
                  >> stringSpaces
                  >> ch_p('{')
                  >> *(entry)
                  >> ch_p('}');

        entry =  ident[add_key(self.data_)]
                  >> stringSpaces
                  >> ch_p('=')
                  >> stringSpaces
                  >> value[add_value(self.data_)]
                  >> ch_p(';')
                  >> spaces;

        ident = +(alnum_p | chset<>("-_.,:()#@&*|") |  space_p);

        value = *(~ch_p(';'));

        stringSpaces = *blank_p;

        spaces = *space_p;
      }

    };

    vrsceneData & data_;
  };

  struct is_comment
  { 
    bool operator()(std::string const& s) const 
    { 
      return s.find("//") != std::string::npos || s.find("#") != std::string::npos; 
    } 
  };


  struct first_is
  {
    first_is(std::string const& s) : s_(s) {}

    template<class Pair>
    bool operator()(Pair const& p) const { return p.first == s_; }

    std::string const& s_;
  };


  class vrsceneImport
  {
    std::string fileName;
    vrsceneData vrscene;

  public:
    vrsceneImport(std::string name):fileName(name){};
    ~vrsceneImport(){};

    void parseFile();
    bool getValue(std::string const& section_type, std::string const& section_name, std::string const& entry, std::string & result);
    void importVrsceneInfo();
  };
}

#endif